
package com.ht.managermentserver.config;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.NumberSerializers;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.ht.managermentserver.utils.LocalDateTimeDeserializer;
import com.ht.managermentserver.utils.LocalDateTimeSerializer;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 配置权限
 *
 * @author czy
 * @package com.ht.managermentserver.config
 * @date 2020/6/4 11:07
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

  @Override
  public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
    converters.add(customJackson2HttpMessageConverter());
  }

  private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

  /**
   * jackson json 格式化配置
   *
   * @return MappingJackson2HttpMessageConverter
   */
  @Bean
  public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
    final MappingJackson2HttpMessageConverter jsonConverter =
      new MappingJackson2HttpMessageConverter();
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(SerializationFeature.WRITE_DATES_WITH_ZONE_ID, false);
    //Date 数据类型
    objectMapper.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_FORMAT));
    //LocalDateTime 数据类型
    final JavaTimeModule jackson_localDateTime_serializer = new JavaTimeModule();
    jackson_localDateTime_serializer.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
    jackson_localDateTime_serializer.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
    objectMapper.registerModule(jackson_localDateTime_serializer);

    //使 注解生效,在LocalDateTime 类型中
    objectMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
      @Override
      public Object findSerializer(Annotated a) {
        if (a instanceof AnnotatedMethod) {
          //LocalDateTime   数据类型才自定义
          if (a.getType().getRawClass().equals(LocalDateTime.class)) {
            JsonFormat an = a.getAnnotation(JsonFormat.class);
            if (an != null) {
              if (!DEFAULT_DATE_FORMAT.equals(an.pattern())) {
                return new LocalDateTimeSerializer(an.pattern());
              }
            }
          }
        }
        return super.findSerializer(a);
      }
    });
    //统一 Long 转为 String
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
    objectMapper.registerModule(simpleModule);
    jsonConverter.setObjectMapper(objectMapper);


    return jsonConverter;
  }

  /** 所有restful 都加上统一url 前缀 api */
  @Override
  public void configurePathMatch(final PathMatchConfigurer configurer) {
    configurer.addPathPrefix("api", p -> p.isAnnotationPresent(RestController.class));
    final AntPathMatcher pathMatcher = new AntPathMatcher();
    pathMatcher.setCaseSensitive(false);
    configurer.setPathMatcher(pathMatcher);
  }

  @Bean
  public FilterRegistrationBean vueRouterRedirectFilter() {
    final FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new VueRouterRewriteFilterConfig()); // 注册rewrite过滤器
    registration.addUrlPatterns("/ui/*");
    registration.addInitParameter(VueRouterRewriteFilterConfig.VUE_PREFIX, "ui");
    registration.setName("vueRouterRedirectFilter");
    registration.setOrder(-2);
    return registration;
  }
}
